﻿#pragma once

#include <iostream>
#include <cassert>
#include <memory>
#include <algorithm>
#include <functional>

#include <string>
#include <sstream>
#include <fstream>
#include <filesystem>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <unordered_map>
#include <functional>


#ifdef AN_ENGINE_PLATFORM_WIN32
//Windows
#define VK_USE_PLATFORM_WIN32_KHR
#elif AN_ENGINE_PLATFORM_MACOS
//Macos
#define VK_USE_PLATFORM_MACOS_MVK
#elif AN_ENGINE_PLATFORM_LINUX
// Linux
#define VK_USE_PLATFORM_XCB_KHR

#endif

#ifdef AN_DEBUG
#if defined(AN_ENGINE_PLATFORM_WIN32)
#define AN_DEBUGBREAK() __debugbreak()
#elif defined(AN_ENGINE_PLATFORM_LINUX)
#include <signal.h>
#define AN_DEBUGBREAK() raise(SIGTRAP)
#else
#error "Platform doesn't support debugbreak yet!"
#endif
#define AN_ENABLE_ASSERTS
#else
#define AN_DEBUGBREAK()
#endif

#ifdef AN_ENABLE_ASSERTS
    //断言（如果x表示错误则语句运行，{0}占位的"__VA_ARGS__"代表"..."所输入的语句）
#define AN_CORE_ASSERT(x, ...) \
        {if(!x){\
            AN_CORE_ERROR("Assertion Failed: {0}", __VA_ARGS__);\
            AN_DEBUGBREAK();}\
        }
#define AN_ASSERT(x, ...)\
        {if(!x){\
            AN_ERROR("Assertion Failed: {0}", __VA_ARGS__);\
            AN_DEBUGBREAK();}\
        }
#else
#define AN_CORE_ASSERT(x, ...)
#define AN_ASSERT(x, ...)
#endif


#define AN_EXPAND_MACRO(x) x
#define AN_STRINGIFY_MACRO(x) #x
#define AN_ENGINE_GRAPHIC_API_VULKAN

#define Bit(x) (1 << x)
#define AN_BIND_EVENT_FN(fn) std::bind(&fn, this, std::placeholders::_1)

namespace ArsEngine
{
    template<typename T>
    using Ref = std::shared_ptr<T>;
    template<typename T, typename ... Args>
    constexpr Ref<T> CreateRef(Args&& ... args)
    {
        return std::make_shared<T>(std::forward<Args>(args)...);                            // make_shared 的参数是 根据CreateRef所填参数 所动态调整的参数。这些来自CreateRef中的模版参数会被 std::forward 所完美转发
    }

    template<typename T>
    using Scope = std::unique_ptr<T>;
    template<typename T, typename ... Args>
    constexpr Scope<T> CreateScope(Args&& ... args)
    {
        return std::make_unique<T>(std::forward<Args>(args)...);
    }

}
